﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Configuration;
using UpdateLib.Model;
using UpdateLib.Utils;
using Microsoft.Windows.Controls;
using System.Net;
using System.Threading.Tasks;
using Updater.Utils;
using System.IO;

namespace Updater {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window {

        /// <summary>
        /// Update info object
        /// </summary>
        public UpdateInfo _updateInfo = null;
        public static int _threadCount = 0;

        public MainWindow() {
            InitializeComponent();            
        }

        private void CheckForUpdate(){
            bool install = false;

            string[] param =  Environment.GetCommandLineArgs();

            bool isPoxy = bool.Parse(ConfigurationManager.AppSettings["ProxyUse"]);
            
            if(isPoxy)
                _updateInfo = UpdateLib.Utils.Utils.CheckForUpdates(ConfigurationManager.AppSettings["UpdateUrl"], ConfigurationManager.AppSettings["Proxy"], ConfigurationManager.AppSettings["Domain"], ConfigurationManager.AppSettings["User"], ConfigurationManager.AppSettings["Password"]);
            else
                _updateInfo = UpdateLib.Utils.Utils.CheckForUpdates(ConfigurationManager.AppSettings["UpdateUrl"]);
            
            Version curVersionHelp = null;
            Version curVersionLib = null;
            Version curVersionConf = null;
            Version curVersionApp = null;

            if (_updateInfo != null) {

                try {
                    curVersionLib = new Version(param[1]);
                    curVersionHelp = new Version(param[2]);
                    curVersionConf = new Version(param[3]);
                    curVersionApp = new Version(param[4]);
                } catch (Exception) {

                    lblCheckInfo.Content = "No Updates available.";
                    Check.CanSelectNextPage = false;
                    Check.NextButtonVisibility = WizardPageButtonVisibility.Hidden;
                    Check.CanFinish = true;
                }

                // No versions infos -> install?
                if (curVersionLib == null || curVersionHelp == null &&
                   curVersionConf == null || curVersionApp == null) {

                    lblCheckInfo.Content = "Can't find versions information. Do you want to install SWC Invoice.";
                    install = true;
                    curVersionLib = new Version("0.0.0");
                    curVersionHelp = new Version("0.0.0");
                    curVersionConf = new Version("0.0.0");
                    curVersionApp = new Version("0.0.0");

                }

                if ((curVersionLib.CompareTo(_updateInfo.LibVersion) < 0) ||
                    (curVersionHelp.CompareTo(_updateInfo.HelpVersion) < 0) ||
                    (curVersionConf.CompareTo(_updateInfo.ConfVersion) < 0) ||
                    (curVersionApp.CompareTo(_updateInfo.AppVersion) < 0)) {

                    if(!install)
                        lblCheckInfo.Content = "A new Version is available.";

                    chbCheckLib.Content = string.Format("Libraries:\t\tClient Verison: {0}\tCurrent Version: {1}", curVersionLib, _updateInfo.LibVersion);
                    chbCheckHelp.Content = string.Format("Help:\t\tClient Verison: {0}\tCurrent Version: {1}", curVersionHelp, _updateInfo.HelpVersion);
                    chbCheckConf.Content = string.Format("Configuration:\tClient Verison: {0}\tCurrent Version: {1}", curVersionConf, _updateInfo.ConfVersion);
                    chbCheckApp.Content = string.Format("Application:\tClient Verison: {0}\tCurrent Version: {1}", curVersionApp, _updateInfo.AppVersion);

                    chbCheckLib.Visibility = System.Windows.Visibility.Visible;
                    chbCheckHelp.Visibility = System.Windows.Visibility.Visible;
                    chbCheckConf.Visibility = System.Windows.Visibility.Visible;
                    chbCheckApp.Visibility = System.Windows.Visibility.Visible;

                    chbCheckLib.IsChecked = (curVersionLib.CompareTo(_updateInfo.LibVersion) < 0) ? true : false;
                    chbCheckHelp.IsChecked = (curVersionHelp.CompareTo(_updateInfo.HelpVersion) < 0) ? true : false;
                    chbCheckConf.IsChecked = (curVersionConf.CompareTo(_updateInfo.ConfVersion) < 0) ? true : false;
                    chbCheckApp.IsChecked = (curVersionApp.CompareTo(_updateInfo.AppVersion) < 0) ? true : false;

                    Check.CanSelectNextPage = true;
                    Check.NextButtonVisibility = WizardPageButtonVisibility.Visible;
                    Check.CanFinish = false;

                } else {

                    lblCheckInfo.Content = "No Updates available.";

                    Check.CanSelectNextPage = false;
                    Check.NextButtonVisibility = WizardPageButtonVisibility.Hidden;
                    Check.CanFinish = true;
                }
                 
            } else {
                lblCheckInfo.Content = "Can't establish a conection to the update server.";

                Check.CanSelectNextPage = false;
                Check.NextButtonVisibility = WizardPageButtonVisibility.Hidden;
                Check.CanFinish = true;
            }
            
        }

        public static void DownloadFile(string url, string filename, string name, Image result) {
            WebClient client = new WebClient();
            WebProxy wp =  null;
            NetworkCredential nc = null;

            bool isPoxy = bool.Parse(ConfigurationManager.AppSettings["ProxyUse"]);

            if (isPoxy) {
                nc = new NetworkCredential(ConfigurationManager.AppSettings["User"], ConfigurationManager.AppSettings["Password"], ConfigurationManager.AppSettings["Domain"]);
                wp = new WebProxy(ConfigurationManager.AppSettings["Proxy"],false,null, nc);
                client.Proxy = wp;
            }

            MainWindow _mainWindow = (MainWindow)Application.Current.MainWindow;

            //int SecondsToComplete = 30; //Program specific value
            //Duration duration = new Duration(TimeSpan.FromSeconds((SecondsToComplete * 1.35)));
            //DoubleAnimation doubleAnimatiion = new DoubleAnimation(200, duration);

            try {
                TaskScheduler uiThread = TaskScheduler.FromCurrentSynchronizationContext();

                Action MainThreadDoWork = new Action(() => {
                    client.DownloadFile(url, filename);
                });

                //Action ExecuteProgressBar = new Action(() => {
                //    _MainWindow.progressBar.BeginAnimation(System.Windows.Controls.ProgressBar.ValueProperty, doubleAnimatiion);
                //});

                Action FinalThreadDoWOrk = new Action(() => {
                    //_MainWindow.progressBar.Value = 0;   
                    result.Visibility = Visibility.Visible;
                    _threadCount--;
                    if (_threadCount <= 0) {
                        _mainWindow.ResetIsBusy();
                        _mainWindow.Download.NextButtonVisibility = WizardPageButtonVisibility.Visible;
                    }

                });

                _mainWindow.SetIsBusyDownload("Downloading ...");
                _threadCount++;
                Task MainThreadDoWorkTask = Task.Factory.StartNew(() => MainThreadDoWork());

                //Task ExecuteProgressBarTask = new Task(ExecuteProgressBar);
                //ExecuteProgressBarTask.RunSynchronously();

                MainThreadDoWorkTask.ContinueWith(t => FinalThreadDoWOrk(), uiThread);
            } catch (Exception ex) {
                System.Windows.MessageBox.Show("Error", ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        public static void InstallFile(string filename, string output ,Image result) {
            MainWindow _mainWindow = (MainWindow)Application.Current.MainWindow;

            
            try {
                TaskScheduler uiThread = TaskScheduler.FromCurrentSynchronizationContext();

                Action MainThreadDoWork = new Action(() => {
                    Utils.ZipLib.DecompressFile(filename, output);
                });

                //Action ExecuteProgressBar = new Action(() => {
                //    _MainWindow.progressBar.BeginAnimation(System.Windows.Controls.ProgressBar.ValueProperty, doubleAnimatiion);
                //});

                Action FinalThreadDoWOrk = new Action(() => {
                    //_MainWindow.progressBar.Value = 0;   
                    result.Visibility = Visibility.Visible;
                    File.Delete(filename);
                    _threadCount--;
                    if (_threadCount <= 0) {
                        _mainWindow.ResetIsBusy();
                        _mainWindow.Install.NextButtonVisibility = WizardPageButtonVisibility.Visible;
                    }

                });

                _mainWindow.SetIsBusyInstall("Install ...");
                _threadCount++;
                Task MainThreadDoWorkTask = Task.Factory.StartNew(() => MainThreadDoWork());

                //Task ExecuteProgressBarTask = new Task(ExecuteProgressBar);
                //ExecuteProgressBarTask.RunSynchronously();

                MainThreadDoWorkTask.ContinueWith(t => FinalThreadDoWOrk(), uiThread);
            } catch (Exception ex) {
                System.Windows.MessageBox.Show("Error", ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void DownloadFiles() {
            string applicationPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\";

            if (chbCheckLib.IsChecked.HasValue && chbCheckLib.IsChecked.Value) {
                lblDownloadInfoLib.Visibility = System.Windows.Visibility.Visible;
                DownloadFile(_updateInfo.LibUpdateUrl, applicationPath + "ReleaseLib.zip", "Librarie files", imgDownloadInfoLib);
            }

            if (chbCheckHelp.IsChecked.HasValue && chbCheckHelp.IsChecked.Value) {
                lblDownloadInfoHelp.Visibility = System.Windows.Visibility.Visible;
                DownloadFile(_updateInfo.HelpUpdateUrl, applicationPath + "ReleaseHelp.zip", "Help librarie files", imgDownloadInfoHelp);
            }

            if (chbCheckConf.IsChecked.HasValue && chbCheckConf.IsChecked.Value) {
                lblDownloadInfoConf.Visibility = System.Windows.Visibility.Visible;
                DownloadFile(_updateInfo.ConfUpdateUrl, applicationPath + "ReleaseConf.zip", "Configuration files", imgDownloadInfoConf);
            }

            if (chbCheckApp.IsChecked.HasValue && chbCheckApp.IsChecked.Value) {
                lblDownloadInfoApp.Visibility = System.Windows.Visibility.Visible;
                DownloadFile(_updateInfo.AppUpdateUrl, applicationPath + "ReleaseApp.zip", "Application files", imgDownloadInfoApp);
            }
        }

        private void InstallFiles() {
            string applicationPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)+@"\";

            if (chbCheckLib.IsChecked.HasValue && chbCheckLib.IsChecked.Value) {
                lblInstallInfoLib.Visibility = System.Windows.Visibility.Visible;
                InstallFile(applicationPath + "ReleaseLib.zip", applicationPath + @"..\", imgInstallInfoLib);
            }

            if (chbCheckHelp.IsChecked.HasValue && chbCheckHelp.IsChecked.Value) {
                lblInstallInfoHelp.Visibility = System.Windows.Visibility.Visible;
                InstallFile(applicationPath + "ReleaseHelp.zip", applicationPath + @"..\", imgInstallInfoHelp);
            }

            if (chbCheckConf.IsChecked.HasValue && chbCheckConf.IsChecked.Value) {
                lblInstallInfoConf.Visibility = System.Windows.Visibility.Visible;
                InstallFile(applicationPath + "ReleaseConf.zip", applicationPath + @"..\", imgInstallInfoConf);
            }

            if (chbCheckApp.IsChecked.HasValue && chbCheckApp.IsChecked.Value) {
                lblInstallInfoApp.Visibility = System.Windows.Visibility.Visible;
                InstallFile(applicationPath + "ReleaseApp.zip", applicationPath + @"..\", imgInstallInfoApp);
            }
        }

        private void Page_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) {
            WizardPage page = ((WizardPage)sender);

            if (page.IsVisible) {
                switch (page.Name) {
                    case "IntroPage":
                        break;
                    case "Check":
                        CheckForUpdate();
                        break;
                    case "Download":
                        break;
                    case "Install":
                        break;
                    case "End":
                        break;
                default:
                        break;
                }
            }

        }

        private void Page_Loaded(object sender, RoutedEventArgs e) {
            WizardPage page = ((WizardPage)sender);

            if (page.IsVisible) {
                switch (page.Name) {
                    case "Download":
                        lblDownloadInfoLib.Visibility = System.Windows.Visibility.Collapsed;
                        lblDownloadInfoHelp.Visibility = System.Windows.Visibility.Collapsed;
                        lblDownloadInfoConf.Visibility = System.Windows.Visibility.Collapsed;
                        lblDownloadInfoApp.Visibility = System.Windows.Visibility.Collapsed;
                        imgDownloadInfoLib.Visibility = System.Windows.Visibility.Collapsed;
                        imgDownloadInfoHelp.Visibility = System.Windows.Visibility.Collapsed;
                        imgDownloadInfoConf.Visibility = System.Windows.Visibility.Collapsed;
                        imgDownloadInfoApp.Visibility = System.Windows.Visibility.Collapsed;
                        Download.NextButtonVisibility = WizardPageButtonVisibility.Hidden;
                        DownloadFiles();
                        break;
                    case "Install":
                        lblInstallInfoLib.Visibility = System.Windows.Visibility.Collapsed;
                        lblInstallInfoHelp.Visibility = System.Windows.Visibility.Collapsed;
                        lblInstallInfoConf.Visibility = System.Windows.Visibility.Collapsed;
                        lblInstallInfoApp.Visibility = System.Windows.Visibility.Collapsed;
                        imgInstallInfoLib.Visibility = System.Windows.Visibility.Collapsed;
                        imgInstallInfoHelp.Visibility = System.Windows.Visibility.Collapsed;
                        imgInstallInfoConf.Visibility = System.Windows.Visibility.Collapsed;
                        imgInstallInfoApp.Visibility = System.Windows.Visibility.Collapsed;
                        Install.NextButtonVisibility = WizardPageButtonVisibility.Hidden;
                        InstallFiles();
                        break;
                    default:
                        break;
                }
            }
        }







        #region Methods

        /// <summary>
        /// Set the busy indicator to true
        /// </summary>
        /// <param name="title">The title of the progress screen</param>
        public void SetIsBusyDownload(string title = "Download ...") {
            this.busyIndicatorDownload.BusyContent = title;
            this.busyIndicatorDownload.IsBusy = true;
        }

        /// <summary>
        /// Set the busy indicator to true
        /// </summary>
        /// <param name="title">The title of the progress screen</param>
        public void SetIsBusyInstall(string title = "Install ...") {
            this.busyIndicatorInstall.BusyContent = title;
            this.busyIndicatorInstall.IsBusy = true;
        }

        /// <summary>
        /// Set the busy indicator to false
        /// </summary>
        public void ResetIsBusy() {
            this.busyIndicatorInstall.IsBusy = false;
            this.busyIndicatorDownload.IsBusy = false;
        }

        #endregion 






   

        
    }
}
